package com.piggy.sys.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.piggy.common.core.annotation.RepeatSubmit;
import com.piggy.common.core.constant.Constants;
import com.piggy.common.core.constant.OssConstans;
import com.piggy.common.core.constant.UserConstants;
import com.piggy.common.core.domain.R;
import com.piggy.common.core.exception.base.BaseException;
import com.piggy.common.core.utils.file.FileUtils;
import com.piggy.common.core.utils.poi.ExcelUtil;
import com.piggy.common.core.utils.sms.SmsConfig;
import com.piggy.common.core.web.controller.BaseController;
import com.piggy.common.core.web.page.TableDataInfo;
import com.piggy.common.log.annotation.Log;
import com.piggy.common.log.enums.BusinessType;
import com.piggy.common.satoken.annotation.Inner;
import com.piggy.common.satoken.utils.SecurityUtils;
import com.piggy.oss.cloud.CloudStorageConfig;
import com.piggy.oss.cloud.OSSFactory;
import com.piggy.sys.api.bo.OssFileUploadBo;
import com.piggy.sys.api.domain.SysConfig;
import com.piggy.sys.api.domain.SysOss;
import com.piggy.sys.api.vo.SysOssVo;
import com.piggy.sys.domain.bo.SysOssEditBo;
import com.piggy.sys.domain.bo.SysOssQueryBo;
import com.piggy.sys.service.ISysConfigService;
import com.piggy.sys.service.ISysOssService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.util.Arrays;
import java.util.List;

/**
 * 文件上传Controller
 *
 * @author piggy
 * @date 2021-07-20
 */
@Api(value = "文件上传控制器", tags = {"文件上传管理"})
@RequiredArgsConstructor
@RestController
@RequestMapping("/oss")
@Slf4j
public class SysOssController extends BaseController {

    private final ISysOssService iSysOssService;

    private final ISysConfigService iSysConfigService;

    /**
     * m
     * 查询文件上传列表
     */
    @ApiOperation("查询文件上传列表")
    //@SaCheckPermission("oss:oss:list")
    @GetMapping("/list")
    public TableDataInfo<SysOssVo> list(@Validated SysOssQueryBo bo, HttpServletResponse response) {
        response.addHeader("Content-Disposition", "inline;filename=piggy");
        return iSysOssService.queryPageList(bo);
    }

    /**
     * 导出文件上传列表
     */
    @SneakyThrows
    @ApiOperation("导出文件上传列表")
    //@SaCheckPermission("oss:oss:export")
    @Log(title = "文件上传", businessType = BusinessType.EXPORT)
    @GetMapping("/export")
    public void export(HttpServletResponse response, @Validated SysOssQueryBo bo) {
        List<SysOssVo> list = iSysOssService.queryList(bo);
        ExcelUtil<SysOssVo> util = new ExcelUtil<SysOssVo>(SysOssVo.class);
        util.exportExcel(response, list, "文件上传");
    }

    /**
     * 获取消息详细信息
     */
    @ApiOperation("获取短信配置")
    //@SaCheckPermission("incar:oss:config")
    @GetMapping("/config")
    public R<String> getConfig() {
        return success(iSysConfigService.selectConfigByKey(OssConstans.CONTRACT_CLOUDCONFIG));
    }

    /**
     * 获取消息详细信息
     */
    @ApiOperation("修改oss配置")
    //@SaCheckPermission("incar:oss:config")
    @RepeatSubmit
    @PutMapping("/updateConfig")
    public R<Integer> updateConfig(@Validated @RequestBody CloudStorageConfig config) {
        SysConfig sysConfig = iSysConfigService.getConfigByKey(OssConstans.CONTRACT_CLOUDCONFIG);
        if (UserConstants.NOT_UNIQUE.equals(iSysConfigService.checkConfigKeyUnique(sysConfig))) {
            return error("修改参数'" + sysConfig.getConfigName() + "'失败，参数键名已存在");
        }
        sysConfig.setConfigValue(JSONUtil.toJsonStr(config));
        sysConfig.setUpdateBy(SecurityUtils.getUsername());
        return toAjax(iSysConfigService.updateConfig(sysConfig));
    }

    /**
     * 获取消息详细信息
     */
    @ApiOperation("修改短信配置")
    //@SaCheckPermission("incar:msg:config")
    @RepeatSubmit
    @PutMapping("/updateMsgConfig")
    public R<Integer> updateMsgConfig(@Validated @RequestBody SmsConfig config) {
        SysConfig sysConfig = iSysConfigService.getConfigByKey(Constants.ALICLOUDSMS);
        if (UserConstants.NOT_UNIQUE.equals(iSysConfigService.checkConfigKeyUnique(sysConfig))) {
            return R.fail("修改参数'" + sysConfig.getConfigName() + "'失败，参数键名已存在");
        }
        sysConfig.setConfigValue(JSONUtil.toJsonStr(config));
        sysConfig.setUpdateBy(SecurityUtils.getUsername());
        return toAjax(iSysConfigService.updateConfig(sysConfig));
    }

    /**
     * 获取文件上传详细信息
     */
    @ApiOperation("获取文件上传详细信息")
    //@SaCheckPermission("oss:oss:query")
    @GetMapping("/{id}")
    public R<SysOssVo> getInfo(@NotNull(message = "主键不能为空")
                               @PathVariable("id") Long id) {
        return R.ok(iSysOssService.queryById(id));
    }

    /**
     * 获取文件上传详细信息, ids逗号分隔
     */
    @ApiOperation("获取文件上传列表详细信息")
    //@SaCheckPermission("oss:oss:query")
    @PostMapping("/files")
    public R<List<SysOssVo>> getFiles(@Validated @RequestBody List<String> idList) {
        return R.ok(iSysOssService.queryIdList(idList));
    }

    /**
     * 上传文件
     */
    //@SaCheckPermission("oss:oss:add")
    @ApiOperation("文件上传(upload)")
    @PostMapping(value = "/upload", produces = {MediaType.APPLICATION_JSON_VALUE},
            consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
    public R<SysOssVo> add(@RequestPart("file") MultipartFile file) throws Exception {
        if (file.isEmpty()) {
            throw new BaseException("上传文件不能为空");
        }
        SysOssVo sysOss = iSysOssService.uploadFileToCLoud(file);
        return R.ok(sysOss);
    }

    /**
     * 上传文件
     */
    @PostMapping(value = "/uploadFileToCloud", produces = {MediaType.APPLICATION_JSON_VALUE},
            consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
    public R<SysOssVo> uploadFileToCloud(@RequestPart("file") MultipartFile file) throws Exception {
        if (file.isEmpty()) {
            throw new BaseException("上传文件不能为空");
        }
        SysOssVo sysOss = iSysOssService.uploadFileToCLoud(file);
        return R.ok(sysOss);
    }

    /**
     * 上传文件
     */
    @PostMapping(value = "/uploadToCloud", produces = {MediaType.APPLICATION_JSON_VALUE},
            consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
    public R<SysOssVo> uploadToCloud(OssFileUploadBo bo) throws Exception {
        if (ObjectUtil.isNull(bo.getContent())) {
            throw new BaseException("上传文件不能为空");
        }
        SysOssVo sysOssVo = iSysOssService.uploadToCloud(bo);
        return R.ok(sysOssVo);
    }

    /**
     * 修改文件上传
     */
    @ApiOperation("修改文件上传")
    //@SaCheckPermission("oss:oss:edit")
    @Log(title = "文件上传", businessType = BusinessType.UPDATE)
    @PutMapping()
    public R<Integer> edit(@Validated @RequestBody SysOssEditBo bo) {
        return ok(iSysOssService.updateByEditBo(bo) ? 1 : 0);
    }

    /**
     * 下载文件
     */
    @SneakyThrows
    @ApiOperation("下载文件")
    @Log(title = "下载文件", businessType = BusinessType.UPDATE)
    @GetMapping("/downloadFile/{id}")
    public void downloadFile(@NotEmpty(message = "主键不能为空")
                             @PathVariable Long id, HttpServletResponse response) {
        SysOss sysOss = iSysOssService.getById(id);
        byte[] bytes = OSSFactory.build().downloadFile(sysOss.getPath());
        FileUtils.setAttachmentResponseHeader(response, sysOss.getName());
        FileUtils.writeBytes(IoUtil.toStream(bytes), response.getOutputStream());
        response.getOutputStream().write(bytes);
    }

    /**
     * 获取文件url
     */
    @SneakyThrows
    @ApiOperation("获取文件url")
    @Log(title = "获取文件url", businessType = BusinessType.UPDATE)
    @GetMapping("/getUrl/{id}")
    public R<SysOssVo> getUrl(@NotEmpty(message = "主键不能为空")
                              @PathVariable Long id, HttpServletResponse response) {
        SysOss sysOss = iSysOssService.getById(id);
        SysOssVo sysOssVo = BeanUtil.toBean(sysOss, SysOssVo.class);
        String url = OSSFactory.build().buildUrl(sysOss.getPath());
        sysOssVo.setUrl(url);

        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with");

        return R.ok(sysOssVo);
    }

    /**
     * 删除文件上传
     */
    @ApiOperation("删除文件上传")
    //@SaCheckPermission("oss:oss:remove")
    @Log(title = "文件上传", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public R<Integer> remove(@NotEmpty(message = "主键不能为空")
                             @PathVariable Long[] ids) {
        return R.ok(iSysOssService.deleteWithValidByIds(Arrays.asList(ids), true) ? 1 : 0);
    }

    @Inner
    @GetMapping("/getSysOssVo")
    public R<SysOssVo> getSysOssVo(@RequestParam("id") Long id) {
        return iSysOssService.getSysOssById(id);
    }
}
